package cn.owng.server.platform.configure;

import cn.owng.server.platform.model.http.response.ResponseBodyEntity;
import cn.owng.server.platform.model.http.response.ResponseCode;
import cn.owng.server.platform.model.vo.MethodArgumentNotValidVO;
import cn.owng.server.platform.model.vo.NullVO;
import cn.owng.server.platform.model.vo.VO;
import com.github.wnameless.json.unflattener.JsonUnflattener;
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 微信公众号请关注: 开源螺丝钉
 * <br>
 * 码云请关注: <a href="https://gitee.com/xiyoufang">https://gitee.com/xiyoufang</a>
 * <br>
 * 哔哩哔哩请关注: <a href="https://space.bilibili.com/438927834">https://space.bilibili.com/438927834</a>
 *
 * @author xiyoufang
 */
@Slf4j
@RestControllerAdvice(annotations = RestController.class)
public class GlobalApiExceptionHandler {


    /**
     * 数据校验异常
     *
     * @param e e
     * @return NotValidResp
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResponseEntity<ResponseBodyEntity<MethodArgumentNotValidVO>> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.warn(e.getMessage());
        MethodArgumentNotValidVO errors = new MethodArgumentNotValidVO();
        errors.putAll(new Gson().fromJson(
                JsonUnflattener.unflatten(
                        e.getBindingResult().getFieldErrors()
                                .stream()
                                .collect(
                                        Collectors.toMap(FieldError::getField,
                                                f -> Optional.ofNullable(f.getDefaultMessage()).orElse(""),
                                                (v1, v2) -> (v1 + ";" + v2)))),
                new TypeToken<LinkedTreeMap<String, Object>>() {
                }.getType()));
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(
                ResponseBodyEntity.create(
                        ResponseCode.METHOD_ARGUMENT_NOT_VALID,
                        errors,
                        "无效的请求参数"));
    }

    /**
     * 系统异常
     *
     * @param e e
     * @return ExceptionResp
     */
    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<ResponseBodyEntity<VO>> handleException(Exception e) {
        log.error(e.getMessage(), e);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(
                ResponseBodyEntity.create(
                        ResponseCode.INTERNAL_SERVER_ERROR,
                        new NullVO(),
                        "系统异常"));
    }
}
